package org.ws.edu.ui;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.ws.edu.model.Answer;
import org.ws.edu.model.Question;
import org.ws.edu.model.Type;

public class ConsoleHandlerUI {
    private static Logger logger = Logger.getLogger(ConsoleHandlerUI.class);
    private final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    private ObjectInputStream in;
    private ObjectOutputStream out;
    private Type type;

    public ConsoleHandlerUI(Socket socket) {
        try {
            in = new ObjectInputStream(socket.getInputStream());
            out = new ObjectOutputStream(socket.getOutputStream());
        } catch (IOException e) {
            logger.warn("Could not get stream of socket ", e);
            System.exit(-1);
        }
    }

    public void chooseTest() {
        try {
            out.writeInt(0);
            out.flush();
            String[] tests = (String[]) in.readObject();
            for (int i = 0; i < tests.length; i++) {
                System.out.println(i + 1 + ". " + tests[i]);
            }
            System.out.println("Enter the number of test...");
            int indexOfTest = Integer.parseInt(br.readLine().trim()) - 1;
            out.writeObject(tests[indexOfTest]);
            out.flush();
        } catch (IOException e) {
            logger.warn("Can't work with socket", e);
            System.exit(-1);
        } catch (ClassNotFoundException e) {
            logger.warn("Can't find class String", e);
            System.exit(-1);
        }

    }

    public void handle() {
        getType();
        respondForQuestions();
        getResult();
    }

    public void getInvalidTestNames() {
        String[] invalidTests = null;
        try {
            out.writeInt(1);
            out.flush();
            invalidTests = (String[]) in.readObject();
        } catch (IOException e) {
            logger.warn("Can't work with socket", e);
            System.exit(-1);
        } catch (ClassNotFoundException e) {
            logger.warn("Can't find class String", e);
            System.exit(-1);
        }
        for (String s : invalidTests) {
            System.out.println(s);
        }

    }

    public void getHelp() {
        String[] help = null;
        try {
            out.writeInt(2);
            out.flush();
            help = (String[]) in.readObject();
        } catch (IOException e) {
            logger.warn("Can't work with socket", e);
            System.exit(-1);
        } catch (ClassNotFoundException e) {
            logger.warn("Can't find class String", e);
            System.exit(-1);
        }
        for (String s : help) {
            System.out.println(s);
        }

    }

    public void exitServerThread() {
        try {
            out.writeInt(3);
            out.flush();
        } catch (IOException e) {
            logger.warn("Can't work with socket", e);
            System.exit(-1);
        }

    }

    private void getType() {
        try {
            type = (Type) in.readObject();
        } catch (IOException e) {
            logger.warn("Can't work with socket", e);
            System.exit(-1);
        } catch (ClassNotFoundException e) {
            logger.warn("Can't find class String", e);
            System.exit(-1);
        }
    }

    private void respondForQuestions() {
        try {
            while (in.readBoolean()) {
                out.writeObject(getUserAnswer((Question) in.readObject()));
                out.flush();
            }
            if (in.readBoolean()) {
                System.out.println("Could you answer on pass questions?");
                if (br.readLine().equalsIgnoreCase("yes")) {
                    out.writeBoolean(true);
                    out.flush();
                    while (in.readBoolean()) {
                        out.writeObject(getUserAnswer((Question) in.readObject()));
                        out.flush();
                    }
                } else {
                    out.writeBoolean(false);
                    out.flush();
                }

            }

        } catch (IOException e) {
            logger.warn("Can't work with socket", e);
            System.exit(-1);
        } catch (ClassNotFoundException e) {
            logger.warn("Can't find class String", e);
            System.exit(-1);
        }

    }

    private List<Answer> getUserAnswer(Question q) throws IOException {
        List<Answer> answers = q.getAllAnswers();
        List<Answer> userAnswers = new ArrayList<Answer>();
        try {
            System.out.println(q.getName());
            for (int i = 0; i < answers.size(); i++) {
                System.out.println(i + 1 + ". " + answers.get(i).getName());
            }
            System.out.println("If Pass question enter \"pass\"");
            System.out.println("enter the answer(-s) ...");
            String answer = br.readLine();
            if (answer.equalsIgnoreCase("pass")) {
                return userAnswers;
            }
            if (type.equals(Type.SCALES) || type.equals(Type.SINGLE_ANSWER_TEST)) {
                userAnswers.add(answers.get(Integer.parseInt(answer.trim()) - 1));
                return userAnswers;
            } else {
                String[] answersIndex = answer.split(",");
                for (String s : answersIndex) {
                    userAnswers.add(answers.get(Integer.parseInt(s.trim()) - 1));
                }

            }

        } catch (NumberFormatException e) {
            System.out.println("Incorrect format of answer \nRetry give answer on question");
            userAnswers = getUserAnswer(q);
            logger.warn("Incorrect format of answer", e);
        } catch (IndexOutOfBoundsException e) {
            System.out.println("Incorrect № of answer \nRetry give answer on question");
            logger.info("Incorrect number of answer");
            userAnswers = getUserAnswer(q);
        }
        return userAnswers;
    }

    private void getResult() {
        try {
            System.out.println((String) in.readObject());
        } catch (IOException e) {
            logger.warn("Can't work with socket", e);
            System.exit(-1);
        } catch (ClassNotFoundException e) {
            logger.warn("Can't find class String", e);
            System.exit(-1);
        }
    }

}